﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing.Design;
using System.Windows.Forms;
using System.Drawing;

namespace ProgNetComponents.Design.Editors
{
    internal class ObjectEditorForm : Form
    {
        private Button btnOK;
        private Button btnCancel;
        private ComboBox cbType;
        private Label label1;
        private Label label2;
        private ComboBox cbBoolean;
        Dictionary<string, Type> types = new Dictionary<string, Type>();
        private Point boxLocation = new Point(112, 43);
        private DateTimePicker dateTimePicker1;
        private TextBox textBox1;
        private Panel panel1;
        private Size boxSize = new Size(192, 21);

        public ObjectEditorForm(params Type[] types)
        {
            InitializeComponent();
            InitTypes(types);
        }
        private void InitializeComponent()
        {
            this.btnOK = new System.Windows.Forms.Button();
            this.btnCancel = new System.Windows.Forms.Button();
            this.cbType = new System.Windows.Forms.ComboBox();
            this.label1 = new System.Windows.Forms.Label();
            this.label2 = new System.Windows.Forms.Label();
            this.cbBoolean = new System.Windows.Forms.ComboBox();
            this.dateTimePicker1 = new System.Windows.Forms.DateTimePicker();
            this.textBox1 = new System.Windows.Forms.TextBox();
            this.panel1 = new System.Windows.Forms.Panel();
            this.panel1.SuspendLayout();
            this.SuspendLayout();
            // 
            // btnOK
            // 
            this.btnOK.DialogResult = System.Windows.Forms.DialogResult.OK;
            this.btnOK.Location = new System.Drawing.Point(116, 77);
            this.btnOK.Name = "btnOK";
            this.btnOK.Size = new System.Drawing.Size(75, 23);
            this.btnOK.TabIndex = 0;
            this.btnOK.Text = "OK";
            this.btnOK.UseVisualStyleBackColor = true;
            // 
            // btnCancel
            // 
            this.btnCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel;
            this.btnCancel.Location = new System.Drawing.Point(197, 77);
            this.btnCancel.Name = "btnCancel";
            this.btnCancel.Size = new System.Drawing.Size(75, 23);
            this.btnCancel.TabIndex = 1;
            this.btnCancel.Text = "Cancel";
            this.btnCancel.UseVisualStyleBackColor = true;
            // 
            // cbType
            // 
            this.cbType.FormattingEnabled = true;
            this.cbType.Location = new System.Drawing.Point(80, 12);
            this.cbType.Name = "cbType";
            this.cbType.Size = new System.Drawing.Size(192, 21);
            this.cbType.TabIndex = 2;
            this.cbType.SelectedIndexChanged += new System.EventHandler(this.cbType_SelectedIndexChanged);
            // 
            // label1
            // 
            this.label1.Location = new System.Drawing.Point(12, 10);
            this.label1.Name = "label1";
            this.label1.Size = new System.Drawing.Size(62, 23);
            this.label1.TabIndex = 3;
            this.label1.Text = "Type:";
            this.label1.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
            // 
            // label2
            // 
            this.label2.Location = new System.Drawing.Point(12, 42);
            this.label2.Name = "label2";
            this.label2.Size = new System.Drawing.Size(62, 23);
            this.label2.TabIndex = 4;
            this.label2.Text = "Value:";
            this.label2.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
            // 
            // cbBoolean
            // 
            this.cbBoolean.FormattingEnabled = true;
            this.cbBoolean.Items.AddRange(new object[] {
            "True",
            "False"});
            this.cbBoolean.Location = new System.Drawing.Point(5, 3);
            this.cbBoolean.Name = "cbBoolean";
            this.cbBoolean.Size = new System.Drawing.Size(192, 21);
            this.cbBoolean.TabIndex = 5;
            this.cbBoolean.Visible = false;
            // 
            // dateTimePicker1
            // 
            this.dateTimePicker1.Location = new System.Drawing.Point(5, 4);
            this.dateTimePicker1.Name = "dateTimePicker1";
            this.dateTimePicker1.Size = new System.Drawing.Size(192, 20);
            this.dateTimePicker1.TabIndex = 6;
            this.dateTimePicker1.Visible = false;
            // 
            // textBox1
            // 
            this.textBox1.Location = new System.Drawing.Point(5, 4);
            this.textBox1.Name = "textBox1";
            this.textBox1.Size = new System.Drawing.Size(192, 20);
            this.textBox1.TabIndex = 7;
            // 
            // panel1
            // 
            this.panel1.Controls.Add(this.textBox1);
            this.panel1.Controls.Add(this.cbBoolean);
            this.panel1.Controls.Add(this.dateTimePicker1);
            this.panel1.Location = new System.Drawing.Point(74, 39);
            this.panel1.Name = "panel1";
            this.panel1.Size = new System.Drawing.Size(200, 32);
            this.panel1.TabIndex = 8;
            // 
            // ObjectEditorForm
            // 
            this.ClientSize = new System.Drawing.Size(282, 106);
            this.Controls.Add(this.panel1);
            this.Controls.Add(this.label2);
            this.Controls.Add(this.label1);
            this.Controls.Add(this.cbType);
            this.Controls.Add(this.btnCancel);
            this.Controls.Add(this.btnOK);
            this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedToolWindow;
            this.MaximizeBox = false;
            this.MinimizeBox = false;
            this.Name = "ObjectEditorForm";
            this.panel1.ResumeLayout(false);
            this.panel1.PerformLayout();
            this.ResumeLayout(false);

        }

        private void InitTypes(params Type[] types)
        {
            if (types != null)
                foreach (Type t in types)
                {
                    this.types.AddIfNotExist(t.Name, t);
                }
            cbType.Items.Add("<NULL>");
            foreach (string s in this.types.Keys)
                cbType.Items.Add(s);
        }

        private void cbType_SelectedIndexChanged(object sender, EventArgs e)
        {
            foreach (Control c in panel1.Controls)
                c.Visible = false;
            if (types.ContainsKey(cbType.SelectedItem.AsString()))
            {
                Type t = types[cbType.SelectedItem.AsString()];
                if (t == typeof(DateTime))
                {
                    dateTimePicker1.Visible = true;
                }
                else if (t == typeof(bool))
                {
                    cbBoolean.Visible = true;
                }
                else
                    textBox1.Visible = true;
            }
        }
        public object EditValue
        {
            get
            {
                if (cbBoolean.Visible)
                    return cbBoolean.SelectedItem.AsBool();
                if (dateTimePicker1.Visible)
                    return dateTimePicker1.Value;
                if (textBox1.Visible)
                {
                    object res = null;
                    try
                    {
                        res = Convert.ChangeType(textBox1.Text, types[cbType.SelectedItem.AsString()]);
                    }
                    catch { }
                    return res;
                }
                return null;
            }
            set
            {
                if (value == null)
                    cbBoolean.SelectedItem = "<NULL>";
                else
                {
                    if (this.types.ContainsKey(value.GetType().Name))
                        cbType.SelectedItem = value.GetType().Name;
                    else
                        cbType.SelectedItem = "<NULL>";
                }
                if (cbBoolean.Visible)
                    cbBoolean.SelectedItem = value.AsBool() ? "True" : "False";
                if (dateTimePicker1.Visible)
                    dateTimePicker1.Value = value.AsDateTime();
                if (textBox1.Visible)
                    textBox1.Text = value.AsString();
            }
        }

    }

    public class BaseObjectEditor : UITypeEditor
    {
        
        private Type[] types = null;
        protected virtual Type[] SupportedTypes {
            get
            {
                if (types == null)
                    types = new Type[]
                    {
                        typeof(string),
                        typeof(int),
                        typeof(decimal),
                        typeof(byte),
                        typeof(DateTime),
                        typeof(bool)
                    };
                return types;
            }
        }
        private ObjectEditorForm form = null;
        private ObjectEditorForm Form
        {
            get
            {
                if (form == null)
                    form = new ObjectEditorForm(SupportedTypes);
                return form;
            }
        }

        public override UITypeEditorEditStyle GetEditStyle(System.ComponentModel.ITypeDescriptorContext context)
        {
            return UITypeEditorEditStyle.Modal;
        }
        public override object EditValue(System.ComponentModel.ITypeDescriptorContext context, IServiceProvider provider, object value)
        {
            Form.EditValue = value;
            if (form.ShowDialog() == DialogResult.OK)
                return form.EditValue;
            return value;
        }
    }
}
